//drawlayer 表示画布的一层
//暂时不做多图层了，意义不大。

import { IO } from "../common/io.js";
import { DrawArea, ImgTool } from "../functions/image/image.js";
import { RectRange } from "../functions/image/rect.js";

class ImageBlock {
    type: string = "imageblock";
    x: number;
    y: number;
    width: number;
    height: number;
    hexdata: string;
}
export class DrawLayer {
    private _edit_img: DrawArea = new DrawArea(32, 32);//编辑画板
    private _select_img: DrawArea
    private haveSelectData: boolean = false;
    //选区只是一个变量
    private _select: RectRange = null;
    getSelect(): RectRange | null {
        return this._select
    }
    Select(select: RectRange): void {
        if (this.haveSelectData) {
            this.applySelectData();
        }
        this._select = select;
    }
    Select_Cancel(): void {
        if (this.haveSelectData) {
            this.applySelectData();
        }
        this._select = null;
    }
    Select_ImgClear() {
        if (this._select_img == null)
            this._select_img = new DrawArea(this._edit_img.getWidth(), this._edit_img.getHeight());
        this._select_img.ClearRect(0, 0, this.getWidth(), this.getHeight());
    }
    Select_ImgDrawImage(img: CanvasImageSource, x: number, y: number, tx: number = 0, ty: number = 0, rotate: number = 0): void {
        if (this._select_img == null)
            this._select_img = new DrawArea(this._edit_img.getWidth(), this._edit_img.getHeight());

        let c2d = this._select_img.getContext();


        c2d.translate(tx, ty);
        c2d.rotate(rotate);
        this._select_img.getContext().drawImage(img, x, y);
        c2d.resetTransform();
        this._select_img.updateBitmap();
    }
    Select_ImgDrawImageScale(img: CanvasImageSource, srcrange: RectRange, xscale: number, yscale: number): void {
        if (this._select_img == null)
            this._select_img = new DrawArea(this._edit_img.getWidth(), this._edit_img.getHeight());

        let c2d = this._select_img.getContext();
        let sx = srcrange.x1;
        let sy = srcrange.y1;
        let w = srcrange.x2 - srcrange.x1;
        let h = srcrange.y2 - srcrange.y1;
        let cx = (srcrange.x2 + srcrange.x1) / 2;
        let cy = (srcrange.y2 + srcrange.y1) / 2;

        let nx = (cx - w / 2 * xscale) | 0
        let ny = (cy - h / 2 * yscale) | 0
        let nw = (w * xscale) | 0
        let nh = (h * yscale) | 0
        c2d.drawImage(img, sx, sy, w, h, nx, ny, nw, nh);
        this._select_img.updateBitmap();
    }

    Select_CopyDataToJson(): ImageBlock {
        if (this._select == null) {
            throw new Error("not have a select value.");
        }
        let data = this._edit_img.getContext().getImageData(this._select.x1, this._select.y1, this._select.x2 - this._select.x1 + 1, this._select.y2 - this._select.y1 + 1);

        let block = new ImageBlock();
        block.x = this._select.x1;
        block.y = this._select.y1;
        block.width = data.width;
        block.height = data.height;
        block.hexdata = IO.Hex2Str(data.data);

        return block;
    }
    async Select_CopyDataToBlob(): Promise<Blob> {
        if (this._select == null) {
            throw new Error("not have a select value.");
        }
        let data = this._edit_img.getContext().getImageData(this._select.x1, this._select.y1, this._select.x2 - this._select.x1 + 1, this._select.y2 - this._select.y1 + 1);
        let b = await ImgTool.ImgData2BlobAsync(data)
        // let b = await this._edit_img.getCanvas().convertToBlob({ "type": "image/png" });
        return b;

        // let block = new ImageBlock();
        // block.x = this._select.x1;
        // block.y = this._select.y1;
        // block.width = data.width;
        // block.height = data.height;
        // block.hexdata = IO.Hex2Str(data.data);

        // return block;
    }
    Select_CutDataToJson(): ImageBlock {
        let b = this.Select_CopyDataToJson();
        this._edit_img.getContext().clearRect(this._select.x1, this._select.y1, this._select.x2 - this._select.x1 + 1, this._select.y2 - this._select.y1 + 1);
        this._edit_img.updateBitmap();
        return b;
    }
    Select_FromImg(img: HTMLImageElement): void {

        if (this.haveSelectData)
            this.applySelectData();

        let data = ImgTool.Img2Data(img);

        if (this._select == null) {
            this._select = new RectRange(0, 0, img.width, img.height);
        }
        if (this._select_img == null)
            this._select_img = new DrawArea(this._edit_img.getWidth(), this._edit_img.getHeight());


        this._select.x1 = 0;
        this._select.y1 = 0;
        this._select.x2 = img.width - 1;
        this._select.y2 = img.height - 1;

        this._select_img.getContext().putImageData(data, this._select.x1, this._select.y1);
        this._select_img.updateBitmap();



        this.haveSelectData = true;
    }
    Select_FromJson(json: ImageBlock): void {

        if (this.haveSelectData)
            this.applySelectData();

        if (this._select == null) {
            this._select = new RectRange(json.x, json.y, json.x + json.width, json.y + json.height);
        }
        if (this._select_img == null)
            this._select_img = new DrawArea(this._edit_img.getWidth(), this._edit_img.getHeight());

        let data = new ImageData(json.width, json.height);
        let _data = IO.Str2Hex(json.hexdata);
        for (var i = 0; i < _data.length; i++)
            data.data[i] = _data[i];

        this._select.x1 = json.x;
        this._select.y1 = json.y;
        this._select.x2 = json.x + json.width - 1;
        this._select.y2 = json.y + json.height - 1;

        this._select_img.getContext().putImageData(data, this._select.x1, this._select.y1);
        this._select_img.updateBitmap();



        this.haveSelectData = true;
    }
    SetSelectData(range: RectRange, data: Uint8Array | Uint8ClampedArray): void {
        if (this.haveSelectData)
            this.applySelectData();
        if (range == null) {
            this._select = null;

            return;
        }


        this._select = range.Clone();

        if (this._select_img == null)
            this._select_img = new DrawArea(range.x2 - range.x1, range.y2 - range.y1);
        let bdata = new ImageData(range.x2 - range.x1, range.y2 - range.y1);
        bdata.data.set(data);
        this._select_img.getContext().putImageData(bdata, this._select.x1, this._select.y1);
        this._select_img.updateBitmap();



        this.haveSelectData = true;
    }
    SetEditData(data: Uint8Array | Uint8ClampedArray): void {
        let bdata = new ImageData(this.getWidth(), this.getHeight());
        bdata.data.set(data);
        this._edit_img.getContext().putImageData(bdata, 0, 0)
        this._edit_img.updateBitmap();
    }

    //将选区拆到单独一层
    copyDataToSelect(): void {
        if (this._select == null) {
            throw new Error("not have a select value.");
        }
        let data = this._edit_img.getContext().getImageData(this._select.x1, this._select.y1, this._select.x2 - this._select.x1 + 1, this._select.y2 - this._select.y1 + 1);
        if (this._select_img == null)
            this._select_img = new DrawArea(this._edit_img.getWidth(), this._edit_img.getHeight());
        this._select_img.getContext().putImageData(data, this._select.x1, this._select.y1);
        this._select_img.updateBitmap();

        this.haveSelectData = true;
    }
    cutDataToSelect(): void {
        if (this._select == null) {
            throw new Error("not have a select value.");
        }
        this.copyDataToSelect();
        this._edit_img.getContext().clearRect(this._select.x1, this._select.y1, this._select.x2 - this._select.x1 + 1, this._select.y2 - this._select.y1 + 1);
        this._edit_img.updateBitmap();
    }
    //将选区合并回来
    applySelectData(): void {
        if (this.haveSelectData == true) {
            this.haveSelectData = false;
            let bmp = this._select_img.getBitmap();
            this._edit_img.getContext().drawImage(bmp, 0, 0);
            this._edit_img.updateBitmap();
            this.Select_ImgClear();
        }
    }
    dropSelectData(): void {
        if (this.haveSelectData == true) {
            this.haveSelectData = false;
            this.Select_ImgClear();
        }
    }

    getBitmap(): ImageBitmap {
        return this._edit_img.getBitmap();
    }
    getBitmapSelect(): ImageBitmap | null {
        if (this.haveSelectData)
            return this._select_img.getBitmap();
        else
            return null;
    }
    getBitmapData(): ImageData {
        return this._edit_img.getContext().getImageData(0, 0, this.getWidth(), this.getHeight());
    }
    getBitmapDataSelect(): ImageData {
        if (this.haveSelectData)
            return this._select_img.getContext().getImageData(this._select.x1, this._select.y1, this._select.x2 - this._select.x1, this._select.y2 - this._select.y1);
        else
            return null;
    }

    DrawArea_Init(img: HTMLImageElement | ImageBitmap): void {
        this._edit_img.DrawArea_Init(img);
    }

    Resize_Scale(neww: number, newh: number, linear: boolean): void {
        this._edit_img.Resize_Scale(neww, newh, linear);
    }
    Resize_Cut(neww: number, newh: number, dirx: number, diry: number): void {
        this._edit_img.Resize_Cut(neww, newh, dirx, diry);
    }
    setWidth(width: number) {
        this._edit_img.setWidth(width);
    }
    setHeight(height: number) {
        this._edit_img.setHeight(height);
    }
    getWidth(): number {
        return this._edit_img.getWidth();
    }
    getHeight(): number {
        return this._edit_img.getHeight();
    }
    updateBitmap(): void {
        this._edit_img.updateBitmap();
    }
    getContext(): OffscreenCanvasRenderingContext2D {
        return this._edit_img.getContext();
    }
    ClearRect(x: number, y: number, w: number, h: number): void {
        this._edit_img.ClearRect(x, y, w, h);
    }
}